﻿@using Radzen.Blazor.Rendering
@inherits RadzenGridLines
@implements IChartSeriesOverlay

@code {
    public RadzenSeriesValueLine()
    {
        Visible = true;
    }

    [Parameter]
    public virtual double Value { get; set; }

    [Parameter]
    public RenderFragment<double> TooltipTemplate { get; set; }

    IChartSeries series;
    [CascadingParameter]
    protected IChartSeries Series
    {
        get
        {
            return series;
        }
        set
        {
            if (value.CoordinateSystem != CoordinateSystem.Cartesian)
            {
                throw new ArgumentException($"Series must use Cartesian coordinate system");
            }
            series = value;
            if (!series.Overlays.Contains(this))
            {
                series.Overlays.Add(this);
            }
        }
    }

    protected virtual string Name => "Value";

    public RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
    {
        double x1, x2, y1, y2;
        if (Chart.ShouldInvertAxes())
        {
            x1 = x2 = categoryScale.Scale(Value);
            if (x1 < 0 || x1 > Chart.CategoryScale.OutputSize)
            {
                return null;
            }
            y1 = 0; y2 = Chart.ValueScale.OutputSize;
        }
        else
        {
            y1 = y2 = valueScale.Scale(Value);
            if (y1 < 0 || y1 > Chart.ValueScale.OutputSize)
            {
                return null;
            }
            x1 = 0; x2 = Chart.CategoryScale.OutputSize;
        }

        var path = $"M{x1.ToInvariantString()} {y1.ToInvariantString()} L{x2.ToInvariantString()} {y2.ToInvariantString()}";
        return
    @<g>
        <Path @key="@($"{path}-{Chart.Series.IndexOf(series)}")" D="@path" Stroke="@Stroke" StrokeWidth="@StrokeWidth" LineType="@LineType" />
    </g>
    ;
    }

    public bool Contains(double mouseX, double mouseY, int tolerance)
    {
        if (Chart.ShouldInvertAxes())
        {
            var a = Chart.CategoryScale.Scale(Value);
            return (mouseY >= -tolerance && mouseY <= Chart.ValueScale.OutputSize + tolerance) && (a >= mouseX - tolerance && a <= mouseX + tolerance);
        }
        else
        {
            var a = Chart.ValueScale.Scale(Value);
            return (mouseX >= -tolerance && mouseX <= Chart.CategoryScale.OutputSize + tolerance) && (a >= mouseY - tolerance && a <= mouseY + tolerance);
        }
    }

    public RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop)
    {
        string text;
        if (Chart.ShouldInvertAxes())
        {
            mouseX = Chart.CategoryScale.Scale(Value) + marginLeft;
            mouseY = Math.Max(marginTop, Math.Min(Chart.ValueScale.OutputSize + marginTop, mouseY));
            text = Chart.ValueAxis.Format(Chart.CategoryScale, Value);
        }
        else
        {
            mouseY = Chart.ValueScale.Scale(Value) + marginTop;
            mouseX = Math.Max(marginLeft, Math.Min(Chart.CategoryScale.OutputSize + marginLeft, mouseX));
            text = Chart.ValueAxis.Format(Chart.ValueScale, Value);
        }

        return builder =>
        {
            builder.OpenComponent<ChartTooltip>(0);

            builder.AddAttribute(1, nameof(ChartTooltip.X), mouseX);
            builder.AddAttribute(2, nameof(ChartTooltip.Y), mouseY);

            builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate == null ? null : TooltipTemplate(Value));

            builder.AddAttribute(8, nameof(ChartTooltip.Title), series.GetTitle());
            builder.AddAttribute(4, nameof(ChartTooltip.Label), Name);
            builder.AddAttribute(5, nameof(ChartTooltip.Value), text);

            builder.AddAttribute(6, nameof(ChartTooltip.Style), $"border: 1px solid {Stroke};");
            builder.AddAttribute(7, nameof(ChartTooltip.Class), "");

            builder.CloseComponent();
        };
    }
}